﻿using System;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Codeflows;
using Codeflows.Results;

namespace Cinderella
{
    public class CinderellaWorm : Codeflow
    {
        [Transactional]
        public Result Start(string url)
        {                        
            return Jump<CinderellaWorm>(c => c.FetchUrl(url));
        }

        public Task<Result> FetchUrl(string url)
        {
            Console.WriteLine("Now visiting: {0}", url);

            return new HttpClient {MaxResponseContentBufferSize = int.MaxValue}
                .SendAsync(
                    new HttpRequestMessage(HttpMethod.Get, url), HttpCompletionOption.ResponseContentRead).ContinueWith(
                        t =>
                            {
                                if (t.Exception != null)
                                    throw t.Exception;

                                var response = t.Result;
                                var task = response.Content.ReadAsStringAsync();
                                task.Wait();
                                var content = task.Result;
                                response.Content.Dispose();
                                response.Dispose();

                                var links =
                                    Regex.Matches(content,
                                                  "(?<=href=\")http.*?(?=\")").Cast<Match>().Select(m => m.Value).
                                        ToArray();

                                return Jump<CinderellaWorm>(c => c.Complete(links));
                            }, TaskContinuationOptions.LongRunning);
        }
        
        [Transactional]
        public Result Complete(string[] outgoingLinks)
        {
            foreach (var outgoingLink in outgoingLinks)
            {
                var link = outgoingLink;

                CodeflowApplication.Create<CinderellaWorm>(c => c.Start(link));
            }

            return End();
        }
    }
}